#include "InputMapTab.h"
#include <QFormLayout>
#include <iostream>
#include <QGroupBox>
#include <QDebug>

InputMapTab::InputMapTab(QWidget *parent, unsigned int inputNumber,
                         InputMapping *defaultMapping)
  : QWidget(parent),
    mEnableBox("Enabled"),
    mMappingButton(0),
    mMappingSlider(0),
    mSliderp2(false),
    mInputFilter(1),
    mInputMapping(defaultMapping)
{
  setObjectName("input"+QString(inputNumber));

  grabKeyboard();
  setFocusPolicy(Qt::StrongFocus);

  mEnableBox.setObjectName(QString::number(inputNumber));
  connect(&mEnableBox, SIGNAL(toggled(bool)), this, SLOT(enableInput(bool)));
  mEnableBox.setChecked(!inputNumber);

  //buttons
  QGridLayout* blayout(new QGridLayout());
  QList<QString> buttonLabels(defaultMapping->mButtonMap.keys());
  for (int i(0); i < buttonLabels.size(); ++i)
  {
    QLabel* l(new QLabel(buttonLabels.at(i)));
    mButtonLabels.push_back(l);
    blayout->addWidget(l, i, 0);

    QPushButton* b(new QPushButton(mInputMapping->mButtonMap.value(l->text()).toString()));
    b->setObjectName(l->text());
    connect(b, SIGNAL(clicked()), this, SLOT(changeButtonMapping()));
    mButtons.push_back(b);
    blayout->addWidget(b, i, 1);

    QProgressBar* p(new QProgressBar());
    p->setObjectName(l->text());
    p->setTextVisible(false);
    p->setMaximumSize(20, 20);
    mProgressBars[l->text()] = p;
    blayout->addWidget(p, i, 2);
  }
  disableButtons(!mEnableBox.isChecked());
  QGroupBox* bbox(new QGroupBox("Buttons"));
  bbox->setLayout(blayout);

  //analogs
  QGridLayout* alayout(new QGridLayout());
  QList<QString> axisLabels(defaultMapping->mAxisMap.keys());
  for(int i(0); i < axisLabels.size(); ++i)
  {
    QLabel* l(new QLabel(axisLabels.at(i)));
    mAnalogSliderLabels.push_back(l);
    alayout->addWidget(l, i, 0);

    QPushButton* b(new QPushButton(mInputMapping->mAxisMap.value(l->text()).toString()));
    b->setObjectName(l->text());
    connect(b, SIGNAL(clicked()), this, SLOT(changeSliderMapping()));
    mAnalogButtons.push_back(b);
    alayout->addWidget(b, i, 1);

    QSlider* s(new QSlider());
    s->setObjectName(l->text());
    s->setEnabled(false);
    s->setMinimum(-100);
    s->setMaximum(100);
    s->setOrientation(Qt::Horizontal);
    mAnalogSliders[s->objectName()] = s;
    alayout->addWidget(s, i, 2);
  }
  disableAnalogSliders(!mEnableBox.isChecked());
  QGroupBox* abox(new QGroupBox("Analogs"));
  abox->setLayout(alayout);

  QGridLayout* layout(new QGridLayout());
  layout->addWidget(&mEnableBox, 0, 1, Qt::AlignRight);
  layout->addWidget(bbox, 1, 0);
  layout->addWidget(abox, 1, 1);
  setLayout(layout);

  mInputFilter.installInputMapping(mInputMapping);
  installEventFilter(&mInputFilter);
  enableInput(!inputNumber);
}

void InputMapTab::slider(QString name, int value)
{
  QSlider* s(mAnalogSliders.value(name, 0));
  if (s)
  {
    s->setValue(value);
  }
}

void InputMapTab::buttonPress(QString name)
{
  QProgressBar* p(mProgressBars.value(name, 0));
  if (p)
  {
    p->setValue(100);
  }
}

void InputMapTab::buttonRelease(QString name)
{
  QProgressBar* p(mProgressBars.value(name, 0));
  if (p)
  {
    p->setValue(0);
  }
}

InputMapping* InputMapTab::inputMapping() const
{
  return mInputMapping;
}

void InputMapTab::enableInput(bool enable)
{
  disableButtons(!enable);
  disableAnalogSliders(!enable);
  if (enable)
  {
    connect(mInputMapping, SIGNAL(axisMovement(QString, int)), this, SLOT(slider(QString, int)));
    connect(mInputMapping, SIGNAL(buttonPress(QString)), this, SLOT(buttonPress(QString)));
    connect(mInputMapping, SIGNAL(buttonRelease(QString)), this, SLOT(buttonRelease(QString)));
  }
  else
  {
    disconnect(mInputMapping, SIGNAL(axisMovement(QString, int)), this, SLOT(slider(QString, int)));
    disconnect(mInputMapping, SIGNAL(buttonPress(QString)), this, SLOT(buttonPress(QString)));
    disconnect(mInputMapping, SIGNAL(buttonRelease(QString)), this, SLOT(buttonRelease(QString)));
    foreach(QSlider* s, mAnalogSliders)
    {
      s->setValue(0);
    }
    foreach(QProgressBar* b, mProgressBars)
    {
      b->setValue(0);
    }
  }
}

void InputMapTab::changeButtonMapping()
{
  QPushButton* b(qobject_cast<QPushButton*>(sender()));
  if (b)
  {
    disableButtons(true);
    b->setText("Press New Button...");
    b->setStyleSheet("color:green;");
    mMappingButton = b;
    grabKeyboard();
    connect(&mInputFilter, SIGNAL(buttonPress(ButtonType)),
            this, SLOT(waitButton(ButtonType)), Qt::UniqueConnection);
  }
}

void InputMapTab::changeSliderMapping()
{
  QPushButton* b(qobject_cast<QPushButton*>(sender()));
  if (b)
  {
    disableAnalogSliders(true);
    b->setText("Move New +Axis...");
    b->setStyleSheet("color:green;");
    mMappingSlider = b;
    grabKeyboard();
    connect(&mInputFilter, SIGNAL(axisMovement(HalfAxisType, int)),
            this, SLOT(waitSlider(HalfAxisType, int)), Qt::UniqueConnection);
    connect(&mInputFilter, SIGNAL(buttonPress(ButtonType)),
            this, SLOT(waitSlider(ButtonType)), Qt::UniqueConnection);
  }
}

void InputMapTab::waitButton(ButtonType k)
{
  if (mMappingButton)
  {
    disconnect(this, SLOT(waitButton(ButtonType)));
    releaseKeyboard();
    mMappingButton->setStyleSheet("");
    QString label(mMappingButton->objectName());
    mInputMapping->mButtonMap[label] = k;
    mMappingButton->setText(mInputMapping->mButtonMap.value(label).toString());
    mMappingButton = 0;
    disableButtons(false);
  }
}

void InputMapTab::waitSlider(HalfAxisType a, int value)
{
  if (mMappingSlider)
  {
    QString label(mMappingSlider->objectName());
    AxisType at = mInputMapping->mAxisMap.value(label);
    if (value)
    {
      if (!mSliderp2)
      {
        at.mPos = a;
        mInputMapping->mAxisMap[label] = at;
        mMappingSlider->setText("+"+a.toString()+"\n"+
                                "Move New -Axis...");
        mSliderp2 = true;
      }
      else if (at.mPos != a)
      {
        disconnect(this, SLOT(waitSlider(ButtonType)));
        disconnect(this, SLOT(waitSlider(HalfAxisType, int)));
        releaseKeyboard();
        mMappingSlider->setStyleSheet("");
        at.mNeg = a;
        mInputMapping->mAxisMap[label] = at;
        mMappingSlider->setText(mInputMapping->mAxisMap.value(label).toString());
        mMappingSlider = 0;
        disableAnalogSliders(false);
        mSliderp2 = false;
      }
    }
  }
}

void InputMapTab::waitSlider(ButtonType a)
{
  HalfAxisType ha;
  ha.mType = HalfAxisType::TYPE_BUTTON;
  ha.mButton = a;
  waitSlider(ha, 100);
}

void InputMapTab::disableButtons(bool disabled)
{
  foreach(QPushButton* b, mButtons)
  {
    b->setDisabled(disabled);
  }
  foreach(QLabel* l, mButtonLabels)
  {
    l->setDisabled(disabled);
  }
}

void InputMapTab::disableAnalogSliders(bool disabled)
{
  foreach(QLabel* l, mAnalogSliderLabels)
  {
    l->setDisabled(disabled);
  }
  foreach(QPushButton* b, mAnalogButtons)
  {
    b->setDisabled(disabled);
  }
}
